package cn.codergege.demo.config

import com.alibaba.druid.support.http.StatViewServlet
import com.alibaba.druid.support.http.WebStatFilter
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder
import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
import org.springframework.boot.web.servlet.FilterRegistrationBean
import org.springframework.boot.web.servlet.ServletRegistrationBean
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary
import org.springframework.context.annotation.Profile
import org.springframework.data.jpa.repository.config.EnableJpaRepositories
import org.springframework.orm.jpa.JpaTransactionManager
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean
import org.springframework.orm.jpa.vendor.Database
import org.springframework.transaction.PlatformTransactionManager
import org.springframework.transaction.annotation.EnableTransactionManagement
import javax.persistence.EntityManager
import javax.sql.DataSource
import org.springframework.jdbc.core.JdbcTemplate
import java.util.*

/**
 *  可以配置的地方:
 *      1. @EnableJpaRepositories: basePackages // repository 所在包
 *      2. getVendorProperties:
 *          1) jpaProperties.database = Database.MYSQL // 设置数据库类型
 *          2) jpaProperties.isShowSql = false // 是否显示 sql
 *          3) ddlAuto { "update" } // dll-auto 生成环境最好设置为 none
 *          4) physicalNamingStrategy(SpringPhysicalNamingStrategy()) // 命名策略
 *      3. emfPrimary: packages("cn.codergege.demo.entity.primary") // 实体类所在包
 */
@Profile("dev", "prod")
@EnableJpaRepositories(
    basePackages = arrayOf("cn.codergege.demo.dao.primary"), // repository 所在包
    entityManagerFactoryRef = "emfPrimary",
    transactionManagerRef = "txmPrimary"
)
@EnableTransactionManagement
@Configuration
class PrimaryConfig {

    @Autowired
    @Qualifier("dataSourcePrimary")
    lateinit var dataSourcePrimary: DataSource

    /**
     *  注入 jpa 配置实体
     */
    @Autowired
    lateinit var jpaProperties: JpaProperties

    /**
     *  设置 jpaProperties
     */
    private fun getVendorProperties(): Map<String, Any> {
        // 设置数据库类型
        jpaProperties.database = Database.MYSQL
        // 是否显示 sql
        jpaProperties.isShowSql = false

        return jpaProperties.getHibernateProperties(
            HibernateSettings()
                .ddlAuto {
                    "update"
                }
                .physicalNamingStrategy(SpringPhysicalNamingStrategy())
        )
    }

    @Bean
    @Primary
    fun jdbcTemplatePrimary(): JdbcTemplate {
        return JdbcTemplate(dataSourcePrimary)
    }

    // 设置实体类所在包
    @Primary
    @Bean
    fun emfPrimary(builder: EntityManagerFactoryBuilder): LocalContainerEntityManagerFactoryBean {
        return builder
            .dataSource(dataSourcePrimary)
            .packages("cn.codergege.demo.entity.primary")
            // primaryPersistenceUnit
            .persistenceUnit("persistenceUnitPrimary")
            .properties(getVendorProperties())
            .build()
    }

    /**
     *  enityManagerPrimary
     */
    @Primary
    @Bean
    fun entityManagerPrimary(builder: EntityManagerFactoryBuilder): EntityManager? {
        return emfPrimary(builder).`object`?.createEntityManager()
    }

    /**
     *  txmPrimary
     */
    @Primary
    @Bean
    fun txmPrimary(builder: EntityManagerFactoryBuilder): PlatformTransactionManager {
        return JpaTransactionManager(emfPrimary(builder).`object`!!)
    }

    // 下面的是 druid 后台管理配置
    @Bean
    fun statViewServlet(): ServletRegistrationBean<StatViewServlet> {
        val bean = ServletRegistrationBean(StatViewServlet(), "/druid/*")

        val initParams = HashMap<String, String>()
        initParams["loginUsername"] = "admin"
        initParams["loginPassword"] = "111111"
        initParams["allow"] = ""//默认就是允许所有访问
//        initParams["deny"]
        bean.initParameters = initParams

        return bean
    }

    // 2. 用于监控的 filter
    @Bean
    fun webStatFilter(): FilterRegistrationBean<WebStatFilter> {
        val bean = FilterRegistrationBean<WebStatFilter>()
        bean.setFilter(WebStatFilter())

        val initParams = HashMap<String, String>()
        initParams["exclusions"] = "*.js,*.css,/druid/*"
        bean.initParameters = initParams
        bean.urlPatterns = Arrays.asList("/*")

        return bean
    }
}